//////////////////////////////////////////////////////////////////////////
//
// This file is a part of APNS provider project.
// Copyright (c) Vladimir Gumenuk, 2013-2014.
//
// PROJECT:         APNS provider
// FILE:            Socket.h: interface for the CSocket class.
// AUTHOR:          Vladimir Gumenuk
// DATE:            22-Dec-2013
// MODIFICATIONS:
//
//////////////////////////////////////////////////////////////////////////

#if !defined(AFX_NETTRANSFER_H__EE8EA360_A1CD_42B2_898D_27CAE8B9C6F0__INCLUDED_)
#define AFX_NETTRANSFER_H__EE8EA360_A1CD_42B2_898D_27CAE8B9C6F0__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define CALL_TIMEOUT_MSEC   20000
#define CALL_TIMEOUT_SEC    20

//////////////////////////////////////////////////////////////////////////
//
class ATL_NO_VTABLE CGMSSocket :
    public CComObjectRootEx<CComMultiThreadModel>,
    public IGMSNetClient,
    public IGMSNetListener
{
public:
    CGMSSocket();
    virtual ~CGMSSocket();

BEGIN_COM_MAP(CGMSSocket)
	COM_INTERFACE_ENTRY_IID(IID_IGMSNetClient,IGMSNetClient)
    COM_INTERFACE_ENTRY_IID(IID_IGMSNetListener,IGMSNetListener)
END_COM_MAP()

    STDMETHOD(Connect)( LPCOLESTR lpstrAddr, DWORD dwPort );
    STDMETHOD(Disconnect)();

    STDMETHOD(Listen)( IGMSNetClient **ppClient );
    STDMETHOD(CancelListen)() { return Disconnect(); };

    STDMETHOD_(int,SendRaw)( LPBYTE pBuffer, DWORD dwSize );
    STDMETHOD_(int,ReceiveRaw)( LPBYTE pBuffer, DWORD dwSize );
    
    STDMETHOD(SendBuffer)( LPBYTE pBuffer, DWORD dwSize );
    STDMETHOD(ReceiveBuffer)( LPBYTE *ppBuffer, DWORD *pdwReceivedSize );
    
    STDMETHOD_(BOOL,IsConnected)();
    STDMETHOD(GetRemoteHostName)( WCHAR szBuf[MAX_PATH] );

    STDMETHOD(GetRemoteIP)( ULONG *pulIP );
    STDMETHOD(GetRemoteIP)( char szBuf[NP_IP_SIZE] );

    STDMETHOD(GetLocalIP)( ULONG *pulIP );
    STDMETHOD(GetLocalIP)( char szBuf[NP_IP_SIZE] );

    STDMETHOD(Send)( IGMSBuffer *pBuffer );
    STDMETHOD(Receive)( IGMSBuffer **ppBuffer );

    STDMETHOD_(DWORD, IsDataAvailable)();

    HRESULT CreateSocket();
    HRESULT CreateListenSocket( DWORD dwPort );
    void    SetSocket( SOCKET hSocket );
    

private:
    HRESULT GetIP( bool bLocal, char szBuf[NP_IP_SIZE] );
    HRESULT GetIP( bool bLocal, ULONG *pulIP );

    BOOL    WaitForReceive( int iTimeOut );

    SOCKET      m_hSocket;
    SOCKADDR_IN m_sockAddr;
    BOOL        m_bConnected;
    CString     m_csHostName;

};

typedef CComObject<CGMSSocket> TGMSSocketImpl;

//////////////////////////////////////////////////////////////////////////
//
class ATL_NO_VTABLE CGMSNetwork :
    public CComObjectRootEx<CComMultiThreadModel>,
    public IGMSNetwork
{
public:
    CGMSNetwork();
    virtual ~CGMSNetwork();

BEGIN_COM_MAP(CGMSNetwork)
	COM_INTERFACE_ENTRY_IID(IID_IGMSNetwork,IGMSNetwork)
END_COM_MAP()

    STDMETHOD(InitNetLayer)();
    STDMETHOD(ShutNetLayer)();
    STDMETHOD(CreateNetClient)( IGMSNetClient **ppClient );
    STDMETHOD(CreateNetListener)( DWORD dwPort, IGMSNetListener **ppListener );
    
private:
    static BOOL m_bNetOk;
};

typedef CComObject<CGMSNetwork> TGMSNetworkImpl;

#endif // !defined(AFX_NETTRANSFER_H__EE8EA360_A1CD_42B2_898D_27CAE8B9C6F0__INCLUDED_)
